#include<stdlib.h>
#include<math.h>
#include "Complex.h"

Complex::Complex()
{
  (*this).real = 1.0;
  (*this).imag = 1.0;
} // this este un pointer spre obiectul curent

Complex::Complex(double real, double imag)
{
  (*this).real = real;
  (*this).imag = imag;
}

Complex::Complex(const Complex& z)
{
  this->real = z.real;
  this->imag = z.imag;
}//constructor de copiere

Complex::Complex(const Complex* z)
{
  this->real = z->real;
  this->imag = z->imag;
}//constructor de copiere

Complex::~Complex()
{
  //std::cout<<"\nObiectul ("<<this->getReal()<<","<<this->getImag()<<") a fost distrus!\n";
}//destructor

double Complex::getReal()
{
  return (*this).real;
}

double Complex::getImag()
{
  return (*this).imag;
}

void Complex::setReal(double re)
{
  (*this).real = re;
}

void Complex::setImag(double im)
{
  (*this).imag = im;
}


Complex Complex::Suma(const Complex& z)
{
  double re = this->real + z.real;
  double im = this->imag + z.imag;
  return Complex(re, im);
}

Complex Complex::Suma(const Complex* z)
{
  double re = this->real + z->real;
  double im = this->imag + z->imag;
  return Complex(re, im);
}

Complex Complex::Suma(double x)
{
  double re = this->real + x;
  return Complex(re, this->imag);	 
}

Complex Complex::Scadere(const Complex& z)
{
  double re = this->real - z.real;
  double im = this->imag - z.imag;
  return Complex(re, im);
}

Complex Complex::Scadere(const Complex* z)
{
  double re = this->real - z->real;
  double im = this->imag - z->imag;
  return Complex(re, im);
}

Complex Complex::Scadere(double x)
{
  double re = this->real - x;
  return Complex(re, this->imag);
}

Complex Complex::Inmultire(const Complex& z)
{
  double re = this->real * z.real - this->imag * z.imag;
  double im = this->real * z.imag + this->imag * z.real;
  return Complex (re, im);
}

Complex Complex::Inmultire(const Complex* z)
{
  double re = this->real * z->real - this->imag * z->imag;
  double im = this->real * z->imag + this->imag * z->real;
  return Complex (re, im);
}

Complex Complex::Inmultire(double x)
{
  double re = this->real * x;
  double im = this->imag * x; 
  return Complex(re, im);	
}

Complex Complex::Impartire(const Complex& z)
{
  if ((z.real == 0) && (z.imag == 0))
  {
    std::cout<<"Error: Division by zero!";
    exit(0);
  }
    else
    {
      double re = (this->real * z.real + this->imag * z.imag)/(z.real * z.real + z.imag * z.imag);
      double im = (this->imag * z.real - this->real * z.imag)/(z.real * z.real + z.imag * z.imag);
      return Complex (re, im);
    }
}

Complex Complex::Impartire(const Complex* z)
{
  if ((z->real == 0) && (z->imag == 0))
  {
    std::cout<<"Error: Division by zero!";
    exit(0);
  }
    else
    {
      double re = (this->real * z->real + this->imag * z->imag)/(z->real * z->real + z->imag * z->imag);
      double im = (this->imag * z->real - this->real * z->imag)/(z->real * z->real + z->imag * z->imag);
      return Complex (re, im);
    }
}

Complex Complex::Impartire(double x)
{
  double re = this->real / x;
  double im = this->imag /x;
  return Complex (re, im);
}

Complex Complex::Conjugat(const Complex& z)
{
  return Complex(z.real, -z.imag);
}
Complex Complex::Conjugat(const Complex* z)
{
  return Complex(z->real, -z->imag);
}

Complex Complex::Radical(void)
{
  double re = sqrt((sqrt(this->real * this->real + this->imag * this->imag) + this->real) /2);
  double im = sqrt((sqrt(this->real * this->real + this->imag * this->imag) - this->real) /2);	
  return Complex(re, im);
}


Complex Complex::operator+(const Complex& z)
{
  double re,im;
  re = (*this).real + z.real;
  im = (*this).imag + z.imag;
  Complex s = Complex(re, im);
  return s;
}

Complex Complex::operator+(const Complex* z)
{
  double re,im;
  re = (*this).real + z->real;
  im = (*this).imag + z->imag;
  Complex s = Complex(re, im);
  return s;
}

Complex Complex::operator+(double x)
{
  double re,im;
  re = (*this).real + x;
  im = (*this).imag;
  Complex s = Complex(re, im);
  return s;
}

Complex Complex::operator-(const Complex& z)
{
  double re,im;
  re = (*this).real - z.real;
  im = (*this).imag - z.imag;
  Complex s = Complex(re, im);
  return s;
}

Complex Complex::operator-(const Complex* z)
{
  double re,im;
  re = (*this).real - z->real;
  im = (*this).imag - z->imag;
  Complex s = Complex(re, im);
  return s;
}

Complex Complex::operator-(double x)
{
  double re,im;
  re = (*this).real - x;
  im = (*this).imag;
  Complex s = Complex(re, im);
  return s;
}

Complex Complex::operator*(const Complex& z)
{
  double re,im;
  re = (*this).real * z.real - (*this).imag + z.imag;
  im = (*this).imag * z.real + (*this).real * z.imag;
  Complex s = Complex(re, im);
  return s;
}

Complex Complex::operator*(const Complex* z)
{
  double re,im;
  re = (*this).real * z->real - (*this).imag + z->imag;
  im = (*this).imag * z->real + (*this).real * z->imag;
  Complex s = Complex(re, im);
  return s;
}

Complex Complex::operator*(const double x)
{
  double re,im;
  re = (*this).real * x;
  im = (*this).imag * x;
  Complex s = Complex(re, im);
  return s;
}

Complex Complex::operator/(const Complex& z)
{
  if((z.real == 0) && (z.imag == 0))
  {
     std::cout<<"Error: Division by zero!";	
     exit(0);
  }
     else
     {
       Complex s;
       s = (*this) * Complex::Conjugat(z) / (z.real * z.real - z.imag * z.imag);
       return s;
     }
}

Complex Complex::operator/(const Complex* z)
{
  if((z->real == 0) && (z->imag == 0))
  {
    std::cout<<"Error: Division by zero!";
    exit(0);
  }
    else
    {
      Complex s;
      s = (*this) * Complex::Conjugat(z) / (z->real * z->real - z->imag * z->imag);
      return s;
    }
}

Complex Complex::operator/(double x)
{
  if(x == 0)
  {
    std::cout<<"Error: Division by zero!";
    exit(0);
  }
    else
    {
      double re,im;
      re = this->real / x;
      im = this->imag / x;
      Complex s = Complex(re, im);
      return s;
    }
}

Complex Complex::operator^(int n)
{
  Complex s;
  s = (*this) * (*this);
  for(int i = 0; i < n - 1; i++)
    s = s * (*this);
  return s;		
}

bool Complex::operator==(const Complex& z)
{
  return (this->real== z.real) &&  (this->imag == z.imag);	
} 

bool Complex::operator==(const Complex* z)
{
  return (this->real == z->real) && (this->imag == z->imag);	
}

bool Complex::operator==(double x)	
{
  return sqrt(this->real *this->real + this->imag * this->imag) == x;
}

/*bool Complex::operator==(double x, const Complex& z)
{
  return (x == z.real) && (z.imag == 0);
}*/

bool Complex::operator!=(const Complex& z)
{
  return (this->real!= z.real) &&  (this->imag != z.imag);	
} 

bool Complex::operator!=(const Complex* z)
{
  return (this->real != z->real) && (this->imag != z->imag);	
}

bool Complex::operator!=(double x)	
{
  return sqrt(this->real *this->real + this->imag * this->imag) != x;
}

/*bool Complex::operator!=(double x, const Complex& z)
{
  return (x != z.real) && (z.imag != 0);
}*/

bool Complex::operator<(const Complex& z)
{
  return sqrt(this->real *this->real + this->imag * this->imag) < sqrt(z.real * z.real + z.imag *z.imag);	
}

bool Complex::operator<(const Complex* z)
{
  return sqrt(this->real *this->real + this->imag * this->imag) < sqrt(z->real * z->real + z->imag *z->imag);	
}

bool Complex::operator<(double x)	
{
  return sqrt(this->real *this->real + this->imag * this->imag) < x;
}

/*bool Complex::operator<(double x, const Complex &z)
{
  return x < sqrt(this->real *this->real + this->imag * this->imag);
}*/

bool Complex::operator<=(const Complex& z)
{
  return sqrt(this->real *this->real + this->imag * this->imag) <= sqrt(z.real * z.real + z.imag *z.imag);
}

bool Complex::operator<=(const Complex* z)
{
  return sqrt(this->real *this->real + this->imag * this->imag) <= sqrt(z->real * z->real + z->imag *z->imag);
}

bool Complex::operator<=(double x)
{
  return sqrt(this->real *this->real + this->imag * this->imag) <= x;
}

/*bool Complex::operator<=(double x, const Complex& z)
{
  return x <= sqrt(this->real *this->real + this->imag * this->imag);
}*/

bool Complex::operator>(const Complex& z)
{
  return sqrt(this->real *this->real + this->imag * this->imag) > sqrt(z.real * z.real + z.imag *z.imag);
}

bool Complex::operator>(const Complex* z)
{
  return sqrt(this->real *this->real + this->imag * this->imag) > sqrt(z->real * z->real + z->imag *z->imag);
}

bool Complex::operator>(double x)
{
  return sqrt(this->real *this->real + this->imag * this->imag) > x;
}

/*bool Complex::operator>(double x, const Complex &z)
{
  return x > sqrt(this->real *this->real + this->imag * this->imag);
}*/

bool Complex::operator>=(const Complex& z)
{
  return sqrt(this->real *this->real + this->imag * this->imag) >= sqrt(z.real * z.real + z.imag *z.imag);
}

bool Complex::operator>=(const Complex* z)
{
  return sqrt(this->real *this->real + this->imag * this->imag) >= sqrt(z->real * z->real + z->imag *z->imag);
}

bool Complex::operator>=(double x)
{
  return sqrt(this->real *this->real + this->imag * this->imag) >= x;
}

/*bool Complex::operator>=(double x, const Complex& z)
{
  return x >= sqrt(this->real *this->real + this->imag * this->imag);
}*/

Complex Complex::operator++()
{
  this->real++;
  this->imag++;
  return *this;
}

Complex Complex::operator++(int)
{
  this->real++;
  this->imag++;
  return *this;
}

Complex Complex::operator--()
{
  this->real--;
  this->imag--;
  return *this;
}

Complex Complex::operator--(int)
{
  this->real--;
  this->imag--;
  return *this;
}

std::istream& operator>>(std::istream& input, Complex& z)
{
  std::cout<<"\nCitire numar complex\nPartea reala:";
  input>>z.real;
  std::cout<<"Partea imaginara:";
  input>>z.imag;
  return input;
}

std::ostream& operator<<(std::ostream& output, Complex z)
{
  output<<"Numar complex:"<<z.real<<" + i*("<<z.imag<<")";
  return output;
}

